<template>
  <div class="tag-difficulty-analysis">
    <div class="charts-container">
      <!--掌握分图-->
      <div class="chart">
        <h3>掌握分前15</h3>
        <div ref="masteryChart" style="width: 100%; height: 500px;"></div>
      </div>
      <!--推荐分图-->
      <div class="chart">
        <h3>推荐分前15</h3>
        <div ref="recommendationChart" style="width: 100%; height: 500px;"></div>
      </div>
    </div>
  </div>
</template>

<script>
import axios from '@/axios';
import * as echarts from 'echarts';

export default {
  name: 'TagDifficultyAnalysis',
  data() {
    return {
      tags: [], // 标签数据
      tagMasteryData: {}, // 标签的掌握分数据
    };
  },
  methods: {
    // 获取数据
    async fetchTagData() {
      try {
        const [tagsResponse, masteryResponse] = await Promise.all([
          axios.get('/api/tag/'),
          axios.get('/api/algorithm/frontend_get_user_tag_mastery/')
        ]);

        this.tags = tagsResponse.data;
        this.tagMasteryData = masteryResponse.data.tag_mastery_data || {};
        this.renderCharts();
      } catch (error) {
        console.error('获取数据失败:', error);
      }
    },

    // 渲染图表
    renderCharts() {
      const masteryTop10 = this.getTop10('mastery_score');
      const recommendationTop10 = this.getTop10('recommendation_score');

      // 渲染掌握分前10的图表
      this.renderChart(this.$refs.masteryChart, masteryTop10, '掌握分');
      // 渲染推荐分前10的图表
      this.renderChart(this.$refs.recommendationChart, recommendationTop10, '推荐分');
    },

    // 获取前10的标签数据，按分数排序
    getTop10(scoreType) {
      return this.tags
        .sort((a, b) => (this.tagMasteryData[b.tag_name]?.[scoreType] || 0) - (this.tagMasteryData[a.tag_name]?.[scoreType] || 0))
        .slice(0, 15) // 取前10
        .map(tag => ({
          name: tag.tag_name,
          value: this.tagMasteryData[tag.tag_name]?.[scoreType] || 0
        }));
    },

    // 渲染单个图表
    renderChart(domElement, data, label) {
      const chart = echarts.init(domElement);

      // 获取数据的最大值，用于标准化球体的大小
      const maxScore = Math.max(...data.map(item => item.value));

      const option = {
        tooltip: {
          trigger: 'item',
          formatter: '{b}: {c}'  // 在鼠标悬浮时显示标签名和分数
        },
        series: [
          {
            type: 'graph',
            layout: 'force',
            roam: true,
            force: {
              repulsion: 600,  // 增强排斥力，避免球体重叠
              edgeLength: [60, 200],  // 边的长度
              gravity: 0.2,  // 调整引力，让球体分散且不聚集
              friction: 0.9, // 设置摩擦系数，使球体间的碰撞和停止更自然
            },
            data: data.map(item => ({
              name: item.name,
              value: item.value,
              symbolSize: this.getBallSize(item.value, maxScore, label), // 计算球体的大小
              itemStyle: {
                color: this.getBallColor(item.value, maxScore), // 给球体上色
                shadowColor: 'rgba(0, 0, 0, 0.3)',  // 添加阴影效果
                shadowBlur: 10, // 阴影模糊
              },
              label: {
                show: true, // 显示标签
                formatter: '{b}', // 显示标签的名称
                color: '#fff',  // 标签文字颜色
                fontSize: 14, // 标签文字大小
                fontWeight: 'bold', // 标签加粗
              }
            })),
            links: [],  // 这里没有需要连接的边
          }
        ]
      };

      chart.setOption(option);
    },

    // 计算球体的大小，确保球体大小在一个合理范围内
    getBallSize(score, maxScore, label) {
      const minSize = 40; // 最小球体大小
      const maxSize = label === '掌握分' ? 156 : 104; // 掌握分球体最大值比推荐分球体更大
      // 根据数据分数计算球体大小，进行标准化
      return (score / maxScore) * (maxSize - minSize) + minSize;
    },

    // 根据分数为球体添加颜色
    getBallColor(score, maxScore) {
      const normalizedScore = score / maxScore;  // 将分数映射到 0-1 之间
      const colorRange = [
        [0, '#FF4C61'],  // 红色
        [0.2, '#F39C11'], // 橙色
        [0.4, '#FFC116'], // 黄色
        [0.6, '#52C41A'], // 绿色
        [0.8, '#3498DB'], // 蓝色
        [1, '#9D3DCF'],  // 紫色
        [1.2, '#0E1D69']  // 额外的颜色范围
      ];
      // 根据 normalizedScore 获取颜色
      for (let i = 0; i < colorRange.length - 1; i++) {
        if (normalizedScore >= colorRange[i][0] && normalizedScore <= colorRange[i + 1][0]) {
          const [lowScore, lowColor] = colorRange[i];
          const [highScore, highColor] = colorRange[i + 1];
          // 计算颜色渐变
          const ratio = (normalizedScore - lowScore) / (highScore - lowScore);
          return this.interpolateColor(lowColor, highColor, ratio);
        }
      }
      return colorRange[colorRange.length - 1][1];  // 默认返回最大值的颜色
    },

    // 颜色渐变的插值计算
    interpolateColor(startColor, endColor, ratio) {
      const startRGB = this.hexToRgb(startColor);
      const endRGB = this.hexToRgb(endColor);
      const interpolatedRGB = startRGB.map((start, i) => Math.round(start + (endRGB[i] - start) * ratio));
      return this.rgbToHex(interpolatedRGB);
    },

    // 十六进制颜色转 RGB
    hexToRgb(hex) {
      const bigint = parseInt(hex.slice(1), 16);
      return [(bigint >> 16) & 255, (bigint >> 8) & 255, bigint & 255];
    },

    // RGB 转十六进制颜色
    rgbToHex(rgb) {
      return `#${rgb.map(x => x.toString(16).padStart(2, '0')).join('')}`;
    }
  },
  mounted() {
    this.fetchTagData();  // 获取数据并渲染图表
  }
};
</script>

<style scoped>
.tag-difficulty-analysis {
  max-width: 90%;
  margin: 20px auto;
  padding: 10px;
  background-color: #f5f5f5;
  border-radius: 8px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.charts-container {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  margin-top: 20px;
}

.chart {
  width: 48%;
  background-color: #ebebeb;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 4px 8px rgba(0, 0, 0,0.1);
}

.chart h3 {
  text-align: center;
  margin-bottom: 15px;
}
</style>

